package org.syncsoft.overalt.communication.impl;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.syncsoft.overalt.common.api.Configuration;
import org.syncsoft.overalt.common.api.Parameter;
import org.syncsoft.overalt.communication.api.IConnectionStatus;
import org.syncsoft.overalt.communication.api.ServerUrl;
import org.syncsoft.overalt.communication.exception.ConnectionException;

/**
 * 
 * @author tptfc
 *
 */
public abstract class AbstractConnectionStatus implements IConnectionStatus {
	private static final String DOUBLE_QUOTE = "\"";
	private DefaultHttpClient httpClient;
	
	public AbstractConnectionStatus(DefaultHttpClient httpClient) {
		setHttpClient(httpClient);
	}
	
	/**
	 * verify if the user is connected
	 * @return
	 */
	public boolean isConnected() {
		boolean test = true;
		
		try {
			if (getHttpClient() != null) {
				HttpGet httpGet = new HttpGet(ServerUrl.getKeepAlive());
				HttpResponse response = getHttpClient().execute(httpGet);
				response.getEntity().consumeContent();
				
				if (response.getStatusLine().getStatusCode() >= 400) {
					test = false;
				}
			}
		} catch (ClientProtocolException e) {
			throw new ConnectionException(e);
		} catch (IOException e) {
			throw new ConnectionException(e);
		}
		
		return test;
	}
	
	/**
	 * @param parameters
	 * @return HttpEntity with parameters
	 */
	protected String buildGetRequestParameters(List<Parameter> parameters) {
		StringBuilder urlQuery = new StringBuilder();
		
		if (parameters != null) {
			boolean isNotFirst = false;
			
			for (Parameter entry: parameters) {
				if (isNotFirst) {
					urlQuery.append("&");
				} else {
					isNotFirst = true;
				}
				
				urlQuery.append(entry.getKey());
				urlQuery.append("=");
				urlQuery.append(entry.getValue());
			}
		}
		
		return urlQuery.toString();
	}
	
	/**
	 * @param parameters
	 * @return HttpEntity with parameters
	 * @throws UnsupportedEncodingException
	 */
	protected HttpEntity buildPostRequestParameters(List<Parameter> parameters) throws UnsupportedEncodingException {
		List<NameValuePair> formParams = new ArrayList<NameValuePair>();
		
		if (parameters != null) {
			for (Parameter entry: parameters) {
				formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		
		return new UrlEncodedFormEntity(formParams, Configuration.getDefaultEncodeParameters());
	}

	/**
	 * @param parameters
	 * @param fileEntityName
	 * @param file
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	protected MultipartEntity buildPostMultipartRequestParameters(List<Parameter> parameters, String fileEntityName, File file) throws UnsupportedEncodingException {
		MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT);
		
		StringBuilder headerFileBuilder = new StringBuilder();
		headerFileBuilder.append("form-data; name=\"file\"; filename=");
		headerFileBuilder.append(DOUBLE_QUOTE);
		headerFileBuilder.append(file.getName());
		headerFileBuilder.append(DOUBLE_QUOTE);
		
		entity.addPart("Content-Disposition", new StringBody(headerFileBuilder.toString()));
		
		FileBody fileBody = new FileBody(file);
		entity.addPart(fileEntityName, fileBody);
		
		if (parameters != null) {
			for (Parameter parameter: parameters) {
				addEntityPartString(parameter, entity);
			}
		}
		
		return entity;
	}
	
	/**
	 * @precondition parameter != null and entity != null
	 * @postcondition entity modified, added the parameter key and value in entity
	 * 
	 * @param parameter
	 * @param entity
	 * @throws UnsupportedEncodingException
	 */
	protected void addEntityPartString(Parameter parameter, MultipartEntity entity) throws UnsupportedEncodingException {
		if (parameter != null && entity != null) {
			entity.addPart(parameter.getKey(), new StringBody(parameter.getValue(), Charset.forName(Configuration.getDefaultEncodeParameters())));
		}
	}

	protected DefaultHttpClient getHttpClient() {
		return httpClient;
	}

	protected void setHttpClient(DefaultHttpClient httpClient) {
		this.httpClient = httpClient;
	}
}
